﻿// -----------------------------------------------------------------------
// <copyright file="RouteUrlBuilder.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace NetFramework.Web.Resources
{
    using System;
    using System.Web;
    using System.Text;
    using System.Web.Routing;
    using System.Collections.Specialized;
    using System.Collections.Generic;

    using NetFramework.Router;
    using NetFramework.Router.Configuration;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class RouteUrlBuilder : IUrlBuilder
    {
        private RequestContext requestContext;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public RouteUrlBuilder()
        {
            requestContext = HttpContext.Current.Request.RequestContext;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public RouteUrlBuilder(RequestContext context)
        {
            this.requestContext = context;
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageAlias"></param>
        /// <returns></returns>
        public string BuildUrl(Enum pageAlias)
        {
            return BuildUrl(pageAlias.ToString());
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageName"></param>
        /// <returns></returns>
        public string BuildUrl(string pageName)
        {
            return BuildUrl(pageName, default(RouteValueDictionary));
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageAlias"></param>
        /// <param name="queryString">The query string. in the format of param1, value1, param2, value2, ...</param>
        /// <returns></returns>
        public string BuildUrl(Enum pageAlias, params string[] queryString)
        {
            RouteValueDictionary values = new RouteValueDictionary();
            for (int i = 0; i < queryString.Length; i += 2)
            {
                if (i + 1 >= queryString.Length)
                {
                    break;
                }
                values.Add(queryString[i], queryString[i + 1]);
            }

            return BuildUrl(pageAlias, values);
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageAlias"></param>
        /// <param name="queryString">The query string. in the format of param1, value1, param2, value2, ...</param>
        /// <returns></returns>
        public string BuildUrl(string pageAlias, params string[] queryString)
        {
            RouteValueDictionary values = new RouteValueDictionary();
            for (int i = 0; i < queryString.Length; i += 2)
            {
                if (i + 1 >= queryString.Length)
                {
                    break;
                }
                values.Add(queryString[i], queryString[i + 1]);
            }

            return BuildUrl(pageAlias, values);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageName"></param>
        /// <returns></returns>
        public string BuildPageUrl(string pageName)
        {
            RouteValueDictionary values = GetRouteValues();

            PageInfo pageInfo = WebResourceConfigHelper.PageInfoConfig.GetPageInfo(pageName);
            return BuildUrl(pageInfo, values);
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageAlias"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public string BuildUrl(Enum pageAlias, NameValueCollection values)
        {
            RouteValueDictionary routeValues = new RouteValueDictionary();
            if (values != null)
            {
                foreach (string key in values)
                {
                    if (string.IsNullOrEmpty(key))
                    {
                        routeValues.Add(key, values[key]);
                    }
                }
            }

            return BuildUrl(pageAlias, new RouteValueDictionary(routeValues));
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageAlias"></param>
        /// <returns></returns>
        public string BuildUrl(Enum pageAlias, RouteValueDictionary values)
        {
            return BuildUrl(pageAlias.ToString(), values);
        }

        /// <summary>
        /// 构造Url
        /// </summary>
        /// <param name="pageName"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public string BuildUrl(string pageName, RouteValueDictionary values)
        {
            if (values == null)
                values = new RouteValueDictionary();

            PageInfo pageInfo = WebResourceConfigHelper.PageInfoConfig.GetPageInfo(pageName);
            return BuildUrl(pageInfo, values);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageInfo"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        private string BuildUrl(PageInfo pageInfo, RouteValueDictionary values)
        {
            string url = string.Empty;
            if (pageInfo != null)
            {
                if (values == null)
                {
                    values = new RouteValueDictionary();
                }
                values.Remove("PageName");

                string rootPath = GetWebsiteDomain(pageInfo.Site);
                VirtualPathData vpd = RouteConfigBuilder.Routes.GetVirtualPath(requestContext, values);
                if (vpd != null && !string.IsNullOrEmpty(vpd.VirtualPath))
                {
                    url = vpd.VirtualPath;
                }
                else
                {
                    string queryString = string.Empty;
                    StringBuilder sb = new StringBuilder();
                    foreach (KeyValuePair<string, object> keyValue in values)
                    {
                        sb.AppendFormat("{0}={1}&",
                                HttpContext.Current.Server.UrlEncode(keyValue.Key),
                                HttpContext.Current.Server.UrlEncode(keyValue.Value as string));
                    }

                    if (sb.Length > 0)
                    {
                        queryString = "?" + sb.ToString().TrimEnd('&');
                    }

                    url = pageInfo.VirtualPath + queryString;
                }

                string applicationPath = requestContext.HttpContext.Request.ApplicationPath;
                if (url.StartsWith(applicationPath, StringComparison.InvariantCultureIgnoreCase))
                {
                    url = url.Substring(applicationPath.Length);
                }

                if (!string.IsNullOrEmpty(rootPath))
                {
                    if (url.StartsWith("~/"))
                        url = url.Substring(2);

                    if (url.StartsWith("/"))
                        url = url.Substring(1);

                    if (string.IsNullOrEmpty(url))
                    {
                        url = rootPath.TrimEnd('/', '\\');
                    }
                    else
                    {
                        url = string.Format("{0}/{1}", rootPath.TrimEnd('/', '\\'), url.TrimStart('/', '\\'));
                    }
                }
            }

            return url;
        }

        private string GetWebsiteDomain(string rootPathName)
        {
            string[] siteArray = WebResourceConfigHelper.WebsiteConfig.GetRootPaths(rootPathName);
            if (siteArray == null || siteArray.Length == 0)
            {
                return string.Empty;
            }
            else
            {
                return siteArray[0];
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestContext"></param>
        /// <returns></returns>
        private RouteValueDictionary GetRouteValues()
        {
            RouteValueDictionary values =
                requestContext.RouteData == null ? new RouteValueDictionary() : requestContext.RouteData.Values;

            HttpRequestBase request = requestContext.HttpContext.Request;
            NameValueCollection queryStrings = request.QueryString ?? new NameValueCollection();
            foreach (string key in queryStrings)
            {
                if (!values.ContainsKey(key))
                {
                    values[key] = queryStrings[key] ?? string.Empty;
                }
            }

            return values;
        }
    }
}
